<?php
class DbUtil
{
	private $_pdo = null;
	private $_isInTransation = false;
	private $_tablePrefix = '';
    private $_isDebug = 0;
	
	public function __construct($dsn, $user, $password, $options = array())
	{
		$this->_pdo = new PDO($dsn, $user, $password, $options);
		$this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //throw exception, not error code;
	}

    /**
     * @param $value 1|0
     */
    public function debug($value)
    {
        $this->_isDebug = $value;
    }

	public function isInTransation()
	{
		return $this->_isInTransation;
	}
	
	/**
	 * beginTransaction
	 * @return boolean true|false
	 */
	public function beginTransaction()
	{
		$this->_isInTransation = true;
		return $this->_pdo->beginTransaction();
	}
	
	/**
	 * commit
	 * @return boolean true|false
	 */
	public function commit()
	{
		$this->_isInTransation = false;
		return $this->_pdo->commit();
	}
	
	/**
	 * rollback
	 * @return boolean true|false
	 */
	public function rollback()
	{
		$this->_isInTransation = false;
		return $this->_pdo->rollback();
	}
	
	public function setTablePrefix($tablePrefix)
	{
		$this->_tablePrefix = $tablePrefix;
	}
	
	public function parseTablePrefix($sql)
	{
		if($this->_tablePrefix)
		{
			$sql = str_replace('{TABLE_PFEFIX}', $this->_tablePrefix, $sql);
		}

        if($this->_isDebug) echo $sql . ';';
		
		return $sql;
	}
	
	/**
	 * Execute an SQL statement and return the number of affected rows
	 * @param string $sql
	 * @return int 
	 */
	public function exec($sql)
	{
		$sql = $this->parseTablePrefix($sql);
		$n = $this->_pdo->exec($sql);
		return ($n) ? $n : 0;
	}
	
	public function query($sql)
	{
		$sql = $this->parseTablePrefix($sql);
		return $this->_pdo->query($sql);
	}
	
	public function fetchOne($sql)
	{
		$sql = $this->parseTablePrefix($sql);
		$rs = $this->_pdo->query($sql);
		return $rs->fetch();
	}
	
	public function fetchAll($sql)
	{
		$sql = $this->parseTablePrefix($sql);
		$rs = $this->_pdo->query($sql);
		return $rs->fetchAll();
	}

    /**
     * 更新
     * @param $tableName
     * @param array $updateValues
     * @param array $wheres
     */
    public function update($tableName, $updateValues = array(), $wheres = array()) {
        $set = array();
        foreach($updateValues as $key => $value) {
            $set[] = "`$key` = '$value'";
        }
        $sql = "UPDATE $tableName SET " . implode(',', $set) . ' WHERE 1 = 1 ' . $this->parseConds($wheres);
        return $this->exec($sql);
    }

    /**
     *
     * @param $tableName
     * @param array $values
     */
    public function insert($tableName, $values = array()) {
        /**
         $values = array(
            'name' => 'aric',
            'sex' => 1
         );
         */
        $k = array();
        $v = array();
        foreach($values as $key => $value) {
            $k[] = '`' . $key . '`';
            $v[] = "'$value'";
        }
        $sql = "INSERT $tableName (" . implode(',', $k) . ') VALUES (' . implode(',', $v) . ')';
        return $this->exec($sql);
    }

    /**
     * @param array $conds
     */
    protected function parseConds($conds = array()) {
        /**
         $conds = array(
            'id' => 2,
            'value' => array('>=', 40),
            'name' => array('LIKE', '%aric%'),
            'sex' => array('NOT IN', '(1,2,3)'),
            '@sql' => 's1 = v1 AND (s2 = 2 OR s3 = 6)'
         )
         */
        $where = '';
        foreach($conds as $key => $item) {
            if($key == '@sql') {
                $where .= ' AND ' . $item;
            } elseif (is_array($item)) {
                $where .= ' AND ' . $key . ' ' . $item[0] . ' ' . $item[1];
            } else {
                $where .= ' AND ' . $key . ' = ' . $item;
            }
        }

        return $where;
    }
}